"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenerateAction = void 0;
const chalk_1 = require("chalk");
const inquirer = require("inquirer");
const get_value_or_default_1 = require("../lib/compiler/helpers/get-value-or-default");
const nest_configuration_loader_1 = require("../lib/configuration/nest-configuration.loader");
const questions_1 = require("../lib/questions/questions");
const readers_1 = require("../lib/readers");
const schematics_1 = require("../lib/schematics");
const ui_1 = require("../lib/ui");
const abstract_action_1 = require("./abstract.action");
class GenerateAction extends abstract_action_1.AbstractAction {
    handle(inputs, options) {
        return __awaiter(this, void 0, void 0, function* () {
            yield generateFiles(inputs.concat(options));
        });
    }
}
exports.GenerateAction = GenerateAction;
const generateFiles = (inputs) => __awaiter(void 0, void 0, void 0, function* () {
    const configuration = yield loadConfiguration();
    const collectionOption = inputs.find(option => option.name === 'collection')
        .value;
    const schematic = inputs.find(option => option.name === 'schematic')
        .value;
    const appName = inputs.find(option => option.name === 'project')
        .value;
    const collection = schematics_1.CollectionFactory.create(collectionOption || configuration.collection);
    const schematicOptions = mapSchematicOptions(inputs);
    schematicOptions.push(new schematics_1.SchematicOption('language', configuration.language));
    const configurationProjects = configuration.projects;
    let sourceRoot = appName
        ? get_value_or_default_1.getValueOrDefault(configuration, 'sourceRoot', appName)
        : configuration.sourceRoot;
    // If you only add a `lib` we actually don't have monorepo: true BUT we do have "projects"
    // Ensure we don't run for new app/libs schematics
    if (shouldAskForProject(schematic, configurationProjects, appName)) {
        const defaultLabel = ' [ Default ]';
        let defaultProjectName = configuration.sourceRoot + defaultLabel;
        for (const property in configurationProjects) {
            if (configurationProjects[property].sourceRoot === configuration.sourceRoot) {
                defaultProjectName = property + defaultLabel;
                break;
            }
        }
        const projects = moveDefaultProjectToStart(configuration, defaultProjectName, defaultLabel);
        const answers = yield askForProjectName(projects);
        const project = answers.appName.replace(defaultLabel, '');
        if (project !== configuration.sourceRoot) {
            sourceRoot = configurationProjects[project].sourceRoot;
        }
    }
    schematicOptions.push(new schematics_1.SchematicOption('sourceRoot', sourceRoot));
    try {
        const schematicInput = inputs.find(input => input.name === 'schematic');
        if (!schematicInput) {
            throw new Error('Unable to find a schematic for this configuration');
        }
        yield collection.execute(schematicInput.value, schematicOptions);
    }
    catch (error) {
        if (error && error.message) {
            console.error(chalk_1.default.red(error.message));
        }
    }
});
const moveDefaultProjectToStart = (configuration, defaultProjectName, defaultLabel) => {
    let projects = Object.keys(configuration.projects);
    if (configuration.sourceRoot !== 'src') {
        projects = projects.filter(p => p !== defaultProjectName.replace(defaultLabel, ''));
    }
    projects.unshift(defaultProjectName);
    return projects;
};
const askForProjectName = (projects) => __awaiter(void 0, void 0, void 0, function* () {
    const questions = [
        questions_1.generateSelect('appName')(ui_1.MESSAGES.PROJECT_SELECTION_QUESTION)(projects),
    ];
    const prompt = inquirer.createPromptModule();
    return yield prompt(questions);
});
const loadConfiguration = () => __awaiter(void 0, void 0, void 0, function* () {
    const loader = new nest_configuration_loader_1.NestConfigurationLoader(new readers_1.FileSystemReader(process.cwd()));
    return loader.load();
});
const mapSchematicOptions = (inputs) => {
    const options = [];
    inputs.forEach(input => {
        if (input.name !== 'schematic' && input.value !== undefined) {
            options.push(new schematics_1.SchematicOption(input.name, input.value));
        }
    });
    return options;
};
const shouldAskForProject = (schematic, configurationProjects, appName) => {
    return (['app', 'sub-module', 'library', 'lib'].includes(schematic) === false &&
        configurationProjects &&
        Object.entries(configurationProjects).length !== 0 &&
        !appName);
};
